/*
*    Phantom v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include ".\java_stream.h"

#include "SSI_SocketLibAPI.h"

java_stream::java_stream(void)
: m_Engine(NULL)
, bCheckSocketError(0)
{
}

java_stream::~java_stream(void)
{
}

void java_stream::operator <<(const char* In){
	Disp(In);
  //cout << In;
}

void java_stream::operator >>(const char* In){
}

void java_stream::Disp(const char *In, SSI_BOOL bAddLine)
{
  
  String s = In;
  if(bAddLine){
    s = s + "\n";
  }

  
  jstring j = env->NewStringUTF(s.Str());
  jint iType = outType;
  env->CallVoidMethod(obj, dispID, j, iType);

	//if(bAddLine){
  //  jstring k = env->NewStringUTF("\n");
  //  env->CallVoidMethod(obj, dispID, k, iType);
	//}
  
  /*
  FILE* FH = fopen("out.txt", "a");
  fprintf(FH, "%s", In);
  if(bAddLine){
    fprintf(FH, "\n");
  }
  fclose(FH);
  */
}

SSI_INT64 java_stream::getline(SSI_CHAR* Buff, SSI_INT64 sz)
{
  if(glID){
    
    jstring j = (jstring)env->CallObjectMethod(obj, glID);
    const char *str = env->GetStringUTFChars(j, 0);

    if(strlen(str) >= sz){
      strcpy(Buff, "");
      return -1;
    }

    sprintf(Buff, "%s", str);

    env->ReleaseStringUTFChars(j, str);
    return (SSI_INT64)strlen(Buff);

  }else{
    strcpy(Buff, "");
    return -1;
  }

  strcpy(Buff, "");
  return -1;  
}


SSI_INT64 java_stream::getDebug(SSI_INT64 LineNum, const SSI_CHAR* File, SSI_CHAR* Buff, SSI_INT64 sz){
	if(!m_Engine) return -1;

  sprintf(Buff, "{%d} %s", LineNum, File);

  String s;
  int iGo = 1;
  while(iGo){
    
    jstring jline = env->NewStringUTF(Buff);
    jstring j = (jstring)env->CallObjectMethod(obj, debugID, jline);
    const char *str = env->GetStringUTFChars(j, 0);
    s = str;
    if(strlen(str) > 0){
      iGo = 0;
    }
    
  }

  sprintf(Buff, "%s", s.Str());
  return strlen(Buff);

  /*
	m_Cmd.Set(SSI_DBG_RQST, s.GetLength(), s.Str());
	if(!m_Cmd.SendMe(*m_Socket)){
		return -1;
	}
	m_SentCtr++;

	if(!m_Cmd.ReadMe(*m_Socket)){
		return -1;
	}
	m_RecvCtr++;

	if(!m_Cmd.IsValidSequence()){
		m_Cmd.Set(RSP_NACK, strlen(AGENT_ERR0002), AGENT_ERR0002);
		m_Cmd.SendMe(*m_Socket);
		m_SentCtr++;
		return -1;
	}

	// Check if valid debug request:
	//   1.  Variable
	//   2.  Breakpoint
	//   3.  Step

	if(m_Cmd.ID == SSI_VAR_RQST){
		if(m_Cmd.Size > (sz - 2)){
			m_Cmd.Set(RSP_NACK, strlen(AGENT_ERR0001), AGENT_ERR0001);
			m_Cmd.SendMe(*m_Socket);
			m_SentCtr++;
			return -1;
		}
		String s = "v ";
		s = s + (char*)m_Cmd.Data;
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else if(m_Cmd.ID == SSI_BPT_ADD){
		String s = "+b ";
		s = s + (char*)m_Cmd.Data;
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else if(m_Cmd.ID == SSI_DBG_EVAL){
		String s = "e ";
		s = s + (char*)m_Cmd.Data;
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else if(m_Cmd.ID == SSI_BPT_RMV){
		String s = "-b ";
		s = s + (char*)m_Cmd.Data;
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else if(m_Cmd.ID == SSI_DBG_GOCTR){
		String s = "g ";
		s = s + (char*)m_Cmd.Data;
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else if(m_Cmd.ID == SSI_DBG_TOLIN){
		String s = "t ";
		s = s + (char*)m_Cmd.Data;
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else if(m_Cmd.ID == SSI_DBG_JMP){
		String s = "j";
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else if(m_Cmd.ID == SSI_DBG_OUT){
		String s = "o";
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else if(m_Cmd.ID == SSI_DBG_STEP){
		String s = "g 1";
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else if(m_Cmd.ID == SSI_BYE){
		String s = "stop";
		Buff = strcpy(Buff, (const char*)s.Str());
		return strlen(Buff);
	}else{
		m_Cmd.Set(RSP_NACK, strlen(AGENT_ERR0001), AGENT_ERR0001);
		m_Cmd.SendMe(*m_Socket);
		m_SentCtr++;
		return -1;
	}

	return -1;
  */
}

/*
SSI_INT64 java_stream::sendDebug()
{
	if(!m_Engine) return 0;

	// Requests and gets the next command in the list
	if(!m_Socket) return 0;
	
	// Assuming m_Cmd has been set
	if(!m_Cmd.SendMe(*m_Socket)){
		return 0;
	}
	m_SentCtr++;

	if(!m_Cmd.ReadMe(*m_Socket)){
		return 0;
	}
	m_RecvCtr++;

	if(!m_Cmd.IsValidSequence() || m_Cmd.ID != RSP_ACK){
		m_Cmd.Set(RSP_NACK, strlen(AGENT_ERR0001), AGENT_ERR0001);
		m_Cmd.SendMe(*m_Socket);
		m_SentCtr++;
		return 0;
	}
 	return 1;
}
*/


void java_stream::ErrorDisp(const char* In, SSI_BOOL bAddLine)
{
  outType = 1;
  if(bCheckSocketError){
    String s;
    s.Format("%s (Socket Code: %d)", In, CSocketSSI::GetLastError());
    Disp(s.Str(), bAddLine);
  }else{
	  Disp(In, bAddLine);
  }
  outType = 0;
	//out_file.Disp(In, bAddLine);
}

void java_stream::WarningDisp(const char* In, SSI_BOOL bAddLine)
{
  outType = 2;
	Disp(In, bAddLine);
  outType = 0;
	//out_file.Disp(In, bAddLine);
}

void java_stream::FailureDisp(const char* In, SSI_BOOL bAddLine)
{
  outType = 3;
	Disp(In, bAddLine);
  outType = 0;
	//out_file.Disp(In, bAddLine);
}

//int java_stream::SetOutFile(const char* fName)
//{
	//out_file.Close();
	//if(!out_file.Open(String(fName), String("w"))){
	//	return 0;
	//}
//	return 1;
//}

void java_stream::SetEngine(CEngine* InEngine)
{
	m_Engine = InEngine;
}

SSI_INT64 java_stream::DisplayDebugVariable(String& Value)
{
  //printf("VALUE: %s\n", Value.Str());

  jstring j;
  //if(Value.GetLength() > 32){
  //  String Small = Value.SubString(0, 31) + "...";
  //  j = env->NewStringUTF(Small.Str());
  //}else{
    j = env->NewStringUTF(Value.Str());
  //}

  
  //if(j == 0){
  //  printf("COULD NOT ALLOCATE STRING\n");
  //}
  jint iType = outType;
  env->CallVoidMethod(obj, dispVarID, j);
  return 1;
}